#include "Thread.hpp"
#include "Task.hpp"
#include  "RingQueue.hpp"

#include <iostream>
#include <string>
#include <vector>
#include <unistd.h>


using namespace ThreadModule;
//任务有两种传入方式，要么封装为Task类，要么是一个函数
using  ringqueue_t = RingQueue<Task>;

class ThreadData
{
    public:
    ThreadData(ringqueue_t & bq,std::string name)
    :_bq(bq),who(name)
    {}

    ringqueue_t &_bq;
    std::string who;
};

void Consumer(ThreadData* td)
{
    while(1)
    {
        sleep(3);
        //1.从阻塞队列中取一个任务
        Task t;
        td->_bq.Pop(&t);

        //2.处理这个任务
        t();
        //std::cout << "Consumer Task,I am :" << td->who << "-------------" << t.ResultToString() << std::endl;
    }
}
void Product(ThreadData* td)
{
    srand(time(nullptr)^ pthread_self());
    while(1)
    {
        sleep(1);
        // //1.生成任务
        // int a = rand() % 10 +1;
        // usleep(1000);
        // int b = rand() % 20 + 1;
        // Task t(a,b);
        Task t = Download;
        //2.把任务放到阻塞队列中
        td->_bq.Enqueue(t);
        //std::cout << "Product Task,I am :" << td->who << "-------------"<< t.DebugToString() << std::endl;
    }
}

void StartConsumer(std::vector<Thread<ThreadData*>> * threads,int num,ringqueue_t& bq)
{
    for(int i = 0;i < num; ++i)
    {
        std::string name = "thread-" + std::to_string(i+1);
        ThreadData* td = new ThreadData(bq,name);
        threads->emplace_back(Consumer,td,name);
        
    }
}
void StartProductor(std::vector<Thread<ThreadData*>> * threads,int num,ringqueue_t& bq)
{
    for(int i = 0;i < num; ++i)
    {
        std::string name = "thread-" + std::to_string(i+1);
        ThreadData* td = new ThreadData(bq,name);

        threads->emplace_back(Product,td,name);
        
    }
}
void WaitAllThread(std::vector<Thread<ThreadData*>>&  threads)
{
    for(auto& e : threads)
    {
        e.Join();
    }
}
void StartAll(std::vector<Thread<ThreadData*>>& threads)
{
    for(auto& e :threads)
    {
        e.Start();
    }
}
int main()
{
    ringqueue_t* bq = new ringqueue_t(5);//队列最多有五个数据
    std::vector<Thread<ThreadData*>> threads;
    StartConsumer(&threads,3,*bq);
    StartProductor(&threads,2,*bq);

    //一切启动
    StartAll(threads);
    WaitAllThread(threads);

}


